package com.whfc.mach.xxl.job;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.whfc.XxlJobConfig;
import com.whfc.common.constant.QueueConst;
import com.whfc.common.enums.WorkState;
import com.whfc.common.util.DateUtil;
import com.whfc.common.util.Gps;
import com.whfc.common.util.MathUtil;
import com.whfc.mach.dto.iot.MachMsg0x01;
import com.whfc.mach.dto.iot.MachMsg0x08;
import com.whfc.mach.dto.iot.MachWorkState;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @Description 设备演示数据生成
 * @Author hw
 * @Date 2021-09-22 17:17
 * @Version 1.0
 */
@Component
@ConditionalOnBean(XxlJobConfig.class)
public class MachDemoDataGenerateJob {

    @Autowired
    private AmqpTemplate amqpTemplate;

    /**
     * 油量
     */
    private final AtomicInteger oilPos = new AtomicInteger(1000);
    /**
     * 设备电量
     */
    private final AtomicInteger machBatteryPower = new AtomicInteger(100);

    @XxlJob("generateMachData")
    public void generateMachData() {
        XxlJobHelper.log("开始生成设备数据...");
        String paramStr = XxlJobHelper.getJobParam();
        if (StringUtils.isEmpty(paramStr)) {
            XxlJobHelper.handleFail("未配置演示数据参数");
            return;
        }
        List<Date> times = new ArrayList<>();
        JSONObject param = JSONObject.parseObject(paramStr);
        if (param.containsKey("startTime") && param.containsKey("endTime")) {
            Date startTime = param.getDate("startTime");
            Date startDate = DateUtil.getDateBegin(startTime);
            Date endTime = param.getDate("endTime");
            Date endDate = DateUtil.getDateEnd(endTime);
            times = DateUtil.getDayListOfMinute(startDate, endDate, 60);
        } else {
            times.add(new Date());
        }
        List<Integer> list = param.getJSONArray("deviceIds").toJavaList(Integer.class);

        for (Date date : times) {
//            if (!isRunTime(date)) {
//                return;
//            }
            Random random = new Random();
            for (Integer deviceId : list) {
                MachMsg0x01 machMsg0x01 = new MachMsg0x01();
                machMsg0x01.setDeviceId(deviceId);
                machMsg0x01.setBatteryPower(machBatteryPower.get() - random.nextInt(5));
                machMsg0x01.setBatteryState(2);
                List<MachWorkState> workStates = new ArrayList<>();
                MachWorkState workState = new MachWorkState();
                workState.setTime(DateUtil.addSeconds(date, random.nextInt(60)));
                workState.setWorkState(generateWorkState());
                workStates.add(workState);
                machMsg0x01.setWorkStates(workStates);
                machMsg0x01.setLatFlag("N");
                machMsg0x01.setLatWgs84(randomLngLat().getLat());
                machMsg0x01.setLngFlag("E");
                machMsg0x01.setLngWgs84(randomLngLat().getLng());
                machMsg0x01.setSpeed(MathUtil.round(random.nextDouble()*100, 2));
                machMsg0x01.setElevation(MathUtil.round(random.nextDouble() * 150, 1));
                machMsg0x01.setOilPos(oilPos.get() - random.nextInt(5));
                try {
                    XxlJobHelper.log("machData:{}", machMsg0x01);
                    amqpTemplate.convertAndSend(QueueConst.MACH_DATA, JSON.toJSONString(machMsg0x01));
                } catch (Exception e) {
                    XxlJobHelper.log("生成设备数据失败.", e);
                }
                MachMsg0x08 machMsg0x08 = new MachMsg0x08();
                amqpTemplate.convertAndSend(QueueConst.MACH_MSG_0X08, JSON.toJSONString(machMsg0x08));
            }

            //油量递减
            oilPos.set(oilPos.get() - 5);
            if (oilPos.get() < 20) {
                oilPos.set(1000);
            }
            //电量递减
            machBatteryPower.set(machBatteryPower.get() - 5);
            if (machBatteryPower.get() < 10) {
                machBatteryPower.set(100);
            }
        }
    }

    /**
     * 生成随机经纬度
     *
     * @return 经纬度
     */
    private Gps randomLngLat() {
        //经纬度区间
//        double minLat = 30.272051D;
//        double maxLat = 30.273051D;
//        double minLng = 120.165039D;
//        double maxLng = 120.166039D;
        //经纬度区间
        double minLat = 34.251515D;
        double maxLat = 34.277193D;
        double minLng = 108.92433D;
        double maxLng = 109.00642D;
        BigDecimal db = new BigDecimal(Math.random() * (maxLng - minLng) + minLng);
        double lon = db.setScale(6, BigDecimal.ROUND_HALF_UP).doubleValue();
        db = new BigDecimal(Math.random() * (maxLat - minLat) + minLat);
        double lat = db.setScale(6, BigDecimal.ROUND_HALF_UP).doubleValue();
        return new Gps(lat, lon);
    }


    /**
     * 生成随机设备状态
     *
     * @return
     */
    private Integer generateWorkState() {
        Random random = new Random();
        int val = random.nextInt(32);
        //工作概率=12/16
        if (val >= 0 && val <= 27) {
            return WorkState.RUN.getValue();
        }
        //怠机概率=2/16
        if (val >= 28 && val <= 29) {
            return WorkState.IDLE.getValue();
        }
        //停机概率=1/16
        if (val == 30) {
            return WorkState.STOP.getValue();
        }
        //休眠概率=1/16
        if (val == 31) {
            return WorkState.SLEEP.getValue();
        }
        return WorkState.ERROR.getValue();
    }


    /**
     * 是否是运行时间
     *
     * @param date 时间
     * @return 是否是运行时间
     */
    private boolean isRunTime(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int hour = calendar.get(Calendar.HOUR_OF_DAY);
        if (hour < 8 || hour > 18 || hour == 12) {
            return false;
        }
        return true;
    }

}
